﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Security;
using System.Runtime.InteropServices;
#if NetFx40
using System.Diagnostics.Contracts;
#endif

namespace XYZShell.Helper
{
	public static class TypeHelper
	{
		/// <summary>
		/// 根据类型短字符串(如 byte,sbyte,int,uint,guid,date,datatime等)获取对应类型
		/// </summary>
		/// <param name="type"></param>
		/// <returns></returns>
		public static Type GetTypeByString( string type )
		{
			switch (type.ToLower())
			{
				case "bool":
					return Type.GetType( "System.Boolean", true );
				case "byte":
					return Type.GetType( "System.Byte", true );
				case "sbyte":
					return Type.GetType( "System.SByte", true );
				case "char":
					return Type.GetType( "System.Char", true );
				case "decimal":
					return Type.GetType( "System.Decimal", true );
				case "double":
					return Type.GetType( "System.Double", true );
				case "float":
					return Type.GetType( "System.Single", true );
				case "int":
					return Type.GetType( "System.Int32", true );
				case "uint":
					return Type.GetType( "System.UInt32", true );
				case "long":
					return Type.GetType( "System.Int64", true );
				case "ulong":
					return Type.GetType( "System.UInt64", true );
				case "object":
					return Type.GetType( "System.Object", true );
				case "short":
					return Type.GetType( "System.Int16", true );
				case "ushort":
					return Type.GetType( "System.UInt16", true );
				case "string":
					return Type.GetType( "System.String", true );
				case "date":
				case "datetime":
					return Type.GetType( "System.DateTime", true );
				case "guid":
					return Type.GetType( "System.Guid", true );
				default:
					return Type.GetType( type, true );
			}
		}

		/// <summary>
		///  数值类型数组转换为字节数组
		/// </summary>
		/// <param name="array"></param>
		/// <returns></returns>
		public static byte[] ArrayToBytes( ValueType[] array )
		{
			List<byte> rtn = new List<byte>();
			foreach (ValueType o in array)
			{
				rtn.AddRange( o.GetBytes() );
			}
			return rtn.ToArray();
		}


		/// <summary>
		/// 根据Type获取内置值类型的数据长度
		/// </summary>
		/// <param name="type"></param>
		/// <returns></returns>
		public static int GetSize( this ValueType type )
		{
			return GetSize( type.GetType() );
		}

		/// <summary>
		/// 根据Type获取内置值类型的数据长度
		/// </summary>
		/// <param name="type">值类型</param>
		/// <returns></returns>
		public static int GetSize( this Type type )
		{
			switch (Type.GetTypeCode( type.GetType() ))
			{
				case TypeCode.Single:
					return sizeof( Single );
				case TypeCode.Boolean:
					return sizeof( bool );
				case TypeCode.Byte:
					return sizeof( byte );
				case TypeCode.Char:
					return sizeof( char );
				case TypeCode.Decimal:
					return sizeof( decimal );
				case TypeCode.Double:
					return sizeof( double );
				case TypeCode.UInt16:
				case TypeCode.Int16:
					return sizeof( Int16 );
				case TypeCode.UInt32:
				case TypeCode.Int32:
					return sizeof( Int32 );
				case TypeCode.UInt64:
				case TypeCode.Int64:
					return sizeof( Int64 );
				case TypeCode.SByte:
					return sizeof( sbyte );
				default:
					{
#if !Portable
#if NetFx40
						Contract.Assert( type.IsValueType );
#endif
						return Marshal.SizeOf( type );
#endif
                        throw new NotSupportedException();
					}



			}
		}

		/// <summary>
		/// 判断指定类型是否为常规值类型(int,short,long等)
		/// </summary>
		/// <param name="t"></param>
		/// <returns></returns>
		public static bool IsCommonValueType( this ValueType o )
		{
			return IsCommonValueType( o.GetType() );
		}

		/// <summary>
		/// 判断指定类型是否为常规值类型(int,short,long等)
		/// </summary>
		/// <param name="t"></param>
		/// <returns></returns>
		public static bool IsCommonValueType( this Type t )
		{
			bool rtn = false;
			switch (Type.GetTypeCode( t.GetType() ))
			{
				case TypeCode.Single:
				case TypeCode.Boolean:
				case TypeCode.Byte:
				case TypeCode.Char:
				case TypeCode.Decimal:
				case TypeCode.Double:
				case TypeCode.UInt16:
				case TypeCode.Int16:
				case TypeCode.UInt32:
				case TypeCode.Int32:
				case TypeCode.UInt64:
				case TypeCode.Int64:
				case TypeCode.SByte:
					rtn = true;
					break;
				default:
					break;

			}
			return rtn;
		}

		/// <summary>
		/// 获取16进制显示的字面数值,即 16进制:34 => 10进制:34
		/// </summary>
		/// <typeparam name="T"></typeparam>
		/// <param name="bs"></param>
		/// <returns></returns>
		public static T GetHexWordValue<T>( this IEnumerable<byte> bs ) where T : struct
		{
			var str = bs.ToHexString();
#if NetFx40
			Contract.Assert( str.All( c =>
			{
				return c <= 0x39 && c >= 0x30;
			} ) ); 
#endif
			return str.ParseTo<T>();
		}

		/// <summary>
		/// 获取16进制显示的字面数值,即 16进制:34 => 10进制:34
		/// </summary>
		public static T GetHexWordValue<T>( string hexStr ) where T : struct
		{
			var str = hexStr;
#if NetFx40
			Contract.Assert( str.All( c =>
			{
				return c <= 0x39 && c >= 0x30;
			} ) ); 
#endif
			return str.ParseTo<T>();
		}

	}
}
